package sii.challenge.modello;

import java.util.HashMap;
import java.util.Map;

/** Classe per rappresentare un generico utente. */
public class Utente {

	/** Identificatore. */
	private int id;
	/** Mappa per rappresentare i ratings dei votati dall'utente. */
	private Map<Integer, Rating> mappaRating;
	/** Media dei ratings. */
	private int avg_ratings;
	/** Varianza dei ratings. */
	private double varianza_ratings;
	
	private String gender;
	
	/** informazioni sui gender dei votati **/
	private int votiM;
	private int votiF;
	private int sommaVotiM;
	private int sommaVotiF;
	
	private double mediaVotiM, mediaVotiF;
	
	/** informazioni sui voti ricevuti **/
	private int votiRicevuti;
	private int sommaVotiRicevuti;
	private int sommaVotiRicevutiM;
	private int votiRicevutiM;
	private int sommaVotiRicevutiF;
	private int votiRicevutiF;
	
	private double mediaVotiRicevuti, mediaVotiRicevutiM, mediaVotiRicevutiF;
	

	/** Costruttore. */
	public Utente(int id) {
		this.id = id;
		mappaRating = new HashMap<Integer, Rating>();
		avg_ratings = 0;
		varianza_ratings = 0;
		
		this.gender = "U";
		
		this.votiF = 0;
		this.votiM = 0;
		this.sommaVotiF = 0;
		this.sommaVotiM = 0;
		
		this.votiRicevuti = 0;
		this.votiRicevutiM = 0;
		this.votiRicevutiF = 0;
		this.sommaVotiRicevuti = 0;
		this.sommaVotiRicevutiM = 0;
		this.sommaVotiRicevutiF = 0;
		
		this.mediaVotiF = -1;
		this.mediaVotiM = -1;
		this.mediaVotiRicevuti = -1;
		this.mediaVotiRicevutiF = -1;
		this.mediaVotiRicevutiM = -1;
	}

	/** Aggiunge un rating alla mappa. */
	public void addRating(Rating rating) {
		this.mappaRating.put(rating.getIdProfile(), rating);
	}
	
	/** Aggiunge le informazioni su un rating ricevuto. **/
	public void addRatingRicevuto(Rating rating){
		this.sommaVotiRicevuti += rating.getRatingValue();
		this.votiRicevuti++;
	}
	public void addRatingRicevutoM(Rating rating){
		this.addRatingRicevuto(rating);
		this.sommaVotiRicevutiM += rating.getRatingValue();
		this.votiRicevutiM++;
	}
	public void addRatingRicevutoF(Rating rating){
		this.addRatingRicevuto(rating);
		this.sommaVotiRicevutiF += rating.getRatingValue();
		this.votiRicevutiF++;
	}

	/** Restituisce la media dei ratings fatti. Se e' la prima volta che viene invocato
	 * la calcola e la salva nella varibiale avgRatings. */
	public int getAvgRating() {
		if (avg_ratings == 0) {
			int somma_parziale = 0;
			int num_rating = 0;
			if (!this.getMappaRating().isEmpty()) {
				for (Rating rating: this.getMappaRating().values()) {
					somma_parziale = somma_parziale + rating.getRatingValue();
					num_rating++;
				}
				this.avg_ratings = somma_parziale / num_rating;
			} else {
				this.avg_ratings = 5;
			}
		}
		return this.avg_ratings;
	}

	/** Restituisce la varianza dei ratings fatti. Se e' la prima volta che viene invocato
	 * la calcola e la salva nella varibiale varianzaRatings. */
	public double getVarianza_rating() {
		if (this.varianza_ratings == 0) {
			double somma_parziale1 = 0;
			double somma_parziale2 = 0;
			for (Rating rat : mappaRating.values()) {
				somma_parziale1 += Math.pow(rat.getRatingValue(),2);
				somma_parziale2 += rat.getRatingValue();
			}
			double N = mappaRating.values().size();
			somma_parziale1 = N*somma_parziale1;
			somma_parziale2 = Math.pow(somma_parziale2, 2);
			if (N != 0) {
				this.varianza_ratings = (1/N)*Math.sqrt(somma_parziale1 - somma_parziale2);
			} else {
				this.varianza_ratings = 0.1;
			}
		}
		return this.varianza_ratings;
	}
	

	/**
	 * Restituisce la media dei voti ricevuti
	 * @return la media dei ricevuti (sia maschili che femminili)
	 */
	public double getMediaVotiRicevuti(){
		if (this.mediaVotiRicevuti < 0)
			if (this.votiRicevuti == 0)
				this.mediaVotiRicevuti = 0;
			else this.mediaVotiRicevuti = (double)(sommaVotiRicevuti)/votiRicevuti;  
		return this.mediaVotiRicevuti;
	}
	
	/**
	 * Restituisce la media dei voti maschili ricevuti
	 * @return la media dei voti maschili ricevuti
	 */
	public double getMediaVotiRicevutiM(){
		if (this.mediaVotiRicevutiM < 0)
		if (this.votiRicevutiM == 0)
			this.mediaVotiRicevutiM = 0;
		else this.mediaVotiRicevutiM = (double)(sommaVotiRicevutiM)/votiRicevutiM;
		return this.mediaVotiRicevutiM;
	}
	
	/**
	 * Restituisce la media dei voti femminili ricevuti
	 * @return la media dei voti femminili ricevuti
	 */
	public double getMediaVotiRicevutiF(){
		if (this.mediaVotiRicevutiF < 0)
			if (this.votiRicevutiF == 0)
				this.mediaVotiRicevutiF = 0;
			else this.mediaVotiRicevutiF = (double)(sommaVotiRicevutiF)/votiRicevutiF;
		return this.mediaVotiRicevutiF;
	}

	/**
	 * Restituisce la media dei voti maschili
	 * @return la media dei voti maschili (sommaVotiM/votiM)
	 */
	public double getMediaVotiM(){
		if (this.mediaVotiM < 0)
			if (votiM == 0)
				this.mediaVotiM = 0;
			else
				this.mediaVotiM = (double)(sommaVotiM)/votiM;
		return this.mediaVotiM;
	}
	
	/**
	 * Restituisce la media dei voti femminili
	 * @return la media dei voti femminili (sommaVotiF/votiF)
	 */
	public double getMediaVotiF(){
		if (this.mediaVotiF < 0)
			if (votiF == 0)
				this.mediaVotiF = 0;
			else
				this.mediaVotiF = (double)(sommaVotiF)/votiF;
		return this.mediaVotiF;
	}
	
	public void addVotoM(Rating r){
		votiM++;
		sommaVotiM += r.getRatingValue();
	}

	public void addVotoF(Rating r){
		votiF++;
		sommaVotiF += r.getRatingValue();
	}
	
	
	/* Metodi Get e Set delle variabili. */
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public Map<Integer, Rating> getMappaRating() {
		return this.mappaRating;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public int getVotiM() {
		return votiM;
	}

	public void setVotiM(int votiM) {
		this.votiM = votiM;
	}

	public int getVotiF() {
		return votiF;
	}

	public void setVotiF(int votiF) {
		this.votiF = votiF;
	}

	public int getSommaVotiM() {
		return sommaVotiM;
	}

	public void setSommaVotiM(int sommaVotiM) {
		this.sommaVotiM = sommaVotiM;
	}

	public int getSommaVotiF() {
		return sommaVotiF;
	}

	public void setSommaVotiF(int sommaVotiF) {
		this.sommaVotiF = sommaVotiF;
	}

	public int getVotiRicevuti() {
		return votiRicevuti;
	}

	public void setVotiRicevuti(int votiRicevuti) {
		this.votiRicevuti = votiRicevuti;
	}

	public int getSommaVotiRicevuti() {
		return sommaVotiRicevuti;
	}

	public void setSommaVotiRicevuti(int sommaVotiRicevuti) {
		this.sommaVotiRicevuti = sommaVotiRicevuti;
	}

	public int getSommaVotiRicevutiM() {
		return sommaVotiRicevutiM;
	}

	public void setSommaVotiRicevutiM(int sommaVotiRicevutiM) {
		this.sommaVotiRicevutiM = sommaVotiRicevutiM;
	}

	public int getVotiRicevutiM() {
		return votiRicevutiM;
	}

	public void setVotiRicevutiM(int votiRicevutiM) {
		this.votiRicevutiM = votiRicevutiM;
	}

	public int getSommaVotiRicevutiF() {
		return sommaVotiRicevutiF;
	}

	public void setSommaVotiRicevutiF(int sommaVotiRicevutiF) {
		this.sommaVotiRicevutiF = sommaVotiRicevutiF;
	}

	public int getVotiRicevutiF() {
		return votiRicevutiF;
	}

	public void setVotiRicevutiF(int votiRicevutiF) {
		this.votiRicevutiF = votiRicevutiF;
	}

	public void setAvg(int double1) {
		this.avg_ratings=double1;
	}

	public void setVarianza_ratings(double varianza_ratings) {
		this.varianza_ratings = varianza_ratings;
	}

	public void setMediaVotiM(double media) {
		this.mediaVotiM = media;
	}

	public void setMediaVotiF(double media) {
		this.mediaVotiF = media;
	}

	public void setMediaVotiRicevuti(double media) {
		this.mediaVotiRicevuti = media;
	}

	public void setMediaVotiRicevutiM(double media) {
		this.mediaVotiRicevutiM = media;
	}

	public void setMediaVotiRicevutiF(double media) {
		this.mediaVotiRicevutiF = media;
	}
	
}
